#pragma once

#include "../Common/Common.h"
#include "NetworkDataRecognizer.h"
#include "../Thread/PosixThreads.h"

#define BOOST_DATE_TIME_NO_LIB	// prevent Boost.asio from linking to Boost.Date_Time lib
#define BOOST_REGEX_NO_LIB		// prevent Boost.asio from linking to Boost.Regex lib

#include <boost/asio.hpp>
#include <boost/bind.hpp>

class PSDF_CORE_DLL_DECL NetworkCenter
{
	enum { BUFFER_MAXLENGTH = 5000 };

public:

	class PSDF_CORE_DLL_DECL Multicast : public PosixThread
	{
		friend NetworkCenter;

	private:
		Multicast() : _socket(_ioService) {}
		Multicast(const Multicast&) : _socket(_ioService) {}
		~Multicast() {}

	public:
		bool joinGroup(const string ipAddr, unsigned short recvPort);
		bool send(char* data, size_t length);
		void run();
		void quit();

	private:
		boost::asio::ip::address		_address;
		unsigned short					_recvPort;
		boost::asio::io_service			_ioService;
		boost::asio::ip::udp::socket	_socket;
		char							_buffer[BUFFER_MAXLENGTH];
	};

	class PSDF_CORE_DLL_DECL TCP : public PosixThread
	{
		friend NetworkCenter;

	private:
		TCP() {}
		TCP(const TCP&) {}
		~TCP() {}

	public:
		bool connect(const string ipAddr, unsigned short port);
		bool send(char* data, size_t length);
		void run();
		void quit();

	};

	class PSDF_CORE_DLL_DECL UDP : public PosixThread
	{
		friend NetworkCenter;

	private:
		UDP() {}
		UDP(const UDP&) {}
		~UDP() {}

	public:
		bool connect(const string ipAddr, unsigned short port);
		bool send(char* data, size_t length);
		void run();
		void quit();
	};

private:
	NetworkCenter();
	NetworkCenter(const NetworkCenter&){}
	~NetworkCenter();

public:
	static NetworkCenter*	inst();
	Multicast*				multicast();
	TCP*					tcp();
	UDP*					udp();

	void					setDataRecognizer(NetworkDataRecognizer* recognizer);

private:
	void					onReceive(char* data, size_t length);

private:
	NetworkDataRecognizer*	_recognizer;
	Multicast*				_multicast;
	TCP*					_tcp;
	UDP*					_udp;
};